Skip to content

Conversation

@hallvictoria
Copy link
Contributor

@hallvictoria hallvictoria commented Dec 5, 2025

Adding support for durabletask-azurefunctions.

  1. Identify which package is being used
  2. Based on package, we call the appropriate decorators
  3. Based on package, we assign the appropriate converter

using_legacy = True
_logger.warning("`azure-functions-durable` is deprecated. " \
"Please migrate to the new `durabletask-azurefunctions` package. " \
"See <AKA.MS LINK HERE> for more details.")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log a warning if azure-functions-durable is being used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message is probably too aggressive before we post the Azure deprecation notice, would suggest for now an info message informing about the new package only.


if using_durable_task and using_legacy:
# Both packages are installed; prefer `durabletask-azurefunctions`.
_logger.warning("Both `azure-functions-durable` and " \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case that the customer has both durable packages, log a warning & prioritize durabletask-azurefunctions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be more unexpected behavior from the Durable extension if both modules are present, this warning suggests that we will safely default to the new module but that might not always be the case. Recommend changing this message to.
"Both azure-functions-durable and durabletask-azurefunctions packages are installed. This may lead to unexpected behavior, please resolve this conflict by removing one of these packages from the Python environment. Decorators from durabletask-azurefunctions will be used."

raise Exception(error_message)
_logger.info("Getting Durable Functions blueprint.")
df = get_durable_package()
df_bp = df.Blueprint()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

df here will now be either azure-functions-durable or durabletask-azurefunctions

class LegacyOrchestrationTriggerConverter(meta.InConverter,
meta.OutConverter,
binding='orchestrationTrigger',
binding=None,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous converters are renamed to "Legacy" with no changes. binding is set to None so that they are not automatically registered


# ---------------- Durable Task Durable Functions Converters ---------------- #
# Durable Function Orchestration Trigger
class OrchestrationTriggerConverter(meta.InConverter,
Copy link
Contributor Author

@hallvictoria hallvictoria Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, converters for durable task package are named OrchestrationTrigger Converter, EntityTriggerConverter, ActivityTriggerConverter, and DurableClientConverter - open to renaming if preferable

def encode(cls, obj: typing.Any, *,
expected_type: typing.Optional[type]) -> meta.Datum:
# Durable function context should be a string
return meta.Datum(type='string', value=obj)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New converters for durable task are currently identical to legacy converters except for this change based on microsoft/durabletask-python#75 (comment).

Will update these converters as needed to be compatible with durable task

_logger.info("Durable Functions package loaded: %s", pkg.__name__)
_logger.info("Current bindings before registration: %s", meta._ConverterMeta._bindings)
# Clear existing bindings if they exist
meta._ConverterMeta._bindings.pop("orchestrationTrigger", None)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should never happen, but just in case - if there are bindings already registered for durable, remove them. Then we add the appropriate converter (Legacy vs. new) based on the durable package brought by the customer

"Attempted to use a Durable Functions decorator, " \
"but the `azure-functions-durable` SDK package could not be " \
"found. Please install `azure-functions-durable` to use " \
"but the `durabletask-azurefunctions` SDK package could not be " \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the case where the customer tries to use a DF decorator (func.FunctionApp) but doesn't have either package installed. df is None, so we raise an error

# Licensed under the MIT License.
import logging

_logger = logging.getLogger('azure.functions.AsgiMiddleware')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the info logs will be removed in the future, just for debugging purposes now

_logger.info("`azure-functions-durable` package not found.")
pass
try:
import durabletask.azurefunctions as durable_functions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to check for both? If durabletask is added, lets directly use it and just add a log that durable task is being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to maintain backwards compatibility with azure-functions-durable. We have to check for both to determine which converter / decorator is being used. This check is only done once though - after that, the df variable will save which module is being used

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants